import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:clean_app/asset/textstyle.dart';
import 'package:clean_app/components/miw.dart';
import 'package:clean_app/provider/login_provider.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:dio/dio.dart';
import 'package:clean_app/asset/color.dart';
import 'package:flutter/services.dart';
import 'package:clean_app/interface/mid_interface.dart';

const String BASE_URL = 'http://121.89.84.104:82';
const String UPLOAD_PATH = '/api/upload-image';
const String UPLOAD_FILE_FIELD = 'file';
const String? API_TOKEN = null;
const String AUTH_HEADER_KEY = 'Authorization';
const String ASK_VLM_POST_PATH = '/api/chat-with-image';
const String FIELD_IMAGE_URL = 'image_url';
const String FIELD_PROMPT = 'prompt';
const String API_KEY = 'restful_demo_key_123';

class VisionTab extends StatefulWidget {
  final String? imageUrl; // 接收外部传入的图片URL
  final File? imageFile; // 接收外部传入的图片文件

  const VisionTab({super.key, this.imageUrl, this.imageFile});

  @override
  State<VisionTab> createState() => _VisionTabState();
}

class _VisionTabState extends State<VisionTab> {
  final _picker = ImagePicker();
  //是否应用大模型
  bool _useLLM = true;

  //大模型 Prompt
  final _promptCtrl = TextEditingController(
      text: "请基于图片给出简要客观描述；判断是否需要在清洁度上改进，并给出可执行建议；给出一个0-10的清洁评分。");

  Map<String, dynamic>? _mlClassify;
  Map<String, dynamic>? _mlScore;
  String? _mlResult;
  String? _llmText;

  XFile? _picked;
  String? _uploadedUrl;
  bool _uploadedOk = false; // ✅ 上传成功显示绿勾
  bool _busy = false;
  double? _progress;
  String? _responseText;

  late final Dio _dio = Dio(
    BaseOptions(
      baseUrl: BASE_URL,
      connectTimeout: const Duration(seconds: 20),
      receiveTimeout: const Duration(seconds: 30),
      headers: API_TOKEN == null
          ? null
          : {
              AUTH_HEADER_KEY: API_TOKEN!.startsWith('Bearer ')
                  ? API_TOKEN
                  : 'Bearer $API_TOKEN',
            },
    ),
  );

  @override
  void initState() {
    super.initState();

    // 处理外部传入的参数
    if (widget.imageUrl != null) {
      setState(() {
        _uploadedUrl = widget.imageUrl;
        _uploadedOk = true;
      });
    } else if (widget.imageFile != null) {
      // 创建临时XFile对象
      _picked = XFile(widget.imageFile!.path);
      // 在下一帧自动上传文件
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _upload();
      });
    }
  }

  void _openPromptSheet() {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.white,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      builder: (ctx) {
        return Padding(
          padding: EdgeInsets.only(
            left: 16,
            right: 16,
            top: 16,
            bottom: MediaQuery.of(ctx).viewInsets.bottom + 16,
          ),
          child: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Container(
                    height: 4,
                    width: 44,
                    decoration: BoxDecoration(
                        color: Colors.black12,
                        borderRadius: BorderRadius.circular(2))),
                const SizedBox(height: 12),
                const Text('大模型 Prompt 调整',
                    style:
                        TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                const SizedBox(height: 12),
                TextField(
                  controller: _promptCtrl,
                  maxLines: 10,
                  decoration: InputDecoration(
                    hintText: '大模型的 Prompt',
                    filled: true,
                    fillColor: Colors.grey.shade100,
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(12),
                      borderSide: BorderSide.none,
                    ),
                    contentPadding: const EdgeInsets.all(12),
                  ),
                ),
                const SizedBox(height: 12),
                SizedBox(
                  width: double.infinity,
                  child: FilledButton(
                    onPressed: () => Navigator.pop(ctx),
                    child: const Text('完成'),
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Future<void> _pick(ImageSource source) async {
    try {
      final x = await _picker.pickImage(
        source: source,
        maxWidth: 2048,
        imageQuality: 92,
      );
      if (x != null) {
        setState(() {
          _picked = x;
          _uploadedUrl = null; // 重新选择后清掉旧 URL
          _uploadedOk = false; // 重新选择后先不显示绿勾
          _responseText = null; // 清除之前的响应
          _upload();
        });
      } else {
        _snack('已取消选择');
      }
    } on PlatformException catch (e) {
      _snack('选图失败（${e.code}）：${e.message ?? ''}');
      debugPrint(
          'ImagePicker PlatformException: code=${e.code}, message=${e.message}');
    } catch (e, st) {
      _snack('选图失败：$e');
      debugPrint('ImagePicker unknown error: $e\n$st');
    }
  }

  Future<void> _upload() async {
    if (_picked == null) {
      _snack('请先选择或拍摄一张图片');
      return;
    }
    setState(() {
      // _busy = true;
      _uploadedOk = false;
      _progress = 0;
    });
    try {
      final file = File(_picked!.path);
      final form = FormData.fromMap({
        UPLOAD_FILE_FIELD: await MultipartFile.fromFile(
          file.path,
          filename: file.path.split('/').last,
        ),
      });

      final resp = await _dio.post(
        UPLOAD_PATH,
        data: form,
        onSendProgress: (sent, total) {
          if (total > 0) setState(() => _progress = sent / total);
        },
      );

      final data = resp.data;
      String? url;
      if (data is Map) {
        url = data['url'] ??
            (data['data'] is Map ? data['data']['url'] : null) ??
            (data['result'] is Map ? data['result']['url'] : null);
      }
      if (url == null || url.isEmpty) {
        throw Exception('上传成功但未解析到图片 URL: $data');
      }
      setState(() {
        _uploadedUrl = url;
        _uploadedOk = true; // ✅ 上传成功，显示绿勾
      });
      _snack('上传成功');
    } catch (e) {
      _snack('上传失败：$e');
    } finally {
      setState(() {
        _busy = false;
        _progress = null;
      });
    }
  }

  Future<String> _askPost(String imageUrl, String prompt, {bool streamUpdate = true}) async {
    final response = await _dio.post(
      ASK_VLM_POST_PATH,
      data: {
        FIELD_IMAGE_URL: imageUrl,
        FIELD_PROMPT: prompt,
      },
      options: Options(
        headers: {'Content-Type': 'application/json'},
        responseType: ResponseType.stream, 
      ),
    );

    final stream = response.data.stream;
    final completer = Completer<String>();
    final StringBuffer buffer = StringBuffer();

    stream.listen(
      (data) {
        String chunk = utf8.decode(data).trim();
        if (chunk.startsWith("data: ")) chunk = chunk.substring(6);
        if (chunk.startsWith("data:"))  chunk = chunk.substring(5);
        if (chunk.startsWith("[DONE]")) chunk = chunk.replaceAll("[DONE]", "").trim();

        buffer.write(chunk);

        if (streamUpdate) {
          setState(() {
            _responseText = buffer.toString();
          });
        }
      },
      onError: (error) {
        if (!completer.isCompleted) completer.completeError(error);
      },
      onDone: () {
        String result = buffer.toString().trim();
        result = result.replaceAll(RegExp(r'^\s*data[:：]\s*', multiLine: true), '');
        final parts = result
            .split('\n')
            .map((e) => e.startsWith('data: ') ? e.substring(6) : (e.startsWith('data:') ? e.substring(5) : e))
            .where((e) => e.isNotEmpty)
            .toList();
        result = parts.join('');
        result = result.replaceAll(RegExp(r'\s*\[DONE\]\s*$'), '');

        if (!completer.isCompleted) {
          completer.complete(result.isEmpty ? '(未解析到答案)' : result);
        }
      },
    );

    return completer.future;
  }

  Future<void> _predict() async {
    final file = File(_picked!.path);

    final results = await Future.wait<Map<String, dynamic>>([
      AiApi().classification(file: file),
      AiApi().scoring(file: file),
    ]);

    _mlClassify = results[0]['data'];
    _mlScore = results[1]['data'];

    _mlResult = _formatMlPretty(_mlClassify, _mlScore);
  }

  String _formatMlPretty(Map<String, dynamic>? cls, Map<String, dynamic>? sc) {
    if (cls == null || sc == null) return '（无数据）';

    final predicted = cls['predicted_class'];
    final confPct = (cls['confidence'] as double? ?? 0) * 100;

    // class_probabilities 里是各类别概率
    final probs =
        (cls['class_probabilities'] as Map?)?.cast<String, num>() ?? {};
    final sorted = probs.entries.toList()
      ..sort((a, b) => b.value.compareTo(a.value));

    final buf = StringBuffer()
      ..writeln('—— 机器学习初步结果 ——')
      ..writeln('分类：$predicted（置信度 $confPct%）')
      ..writeln('各类别概率：');

    for (final e in sorted) {
      final p = (e.value.toDouble() * 100).toStringAsFixed(2);
      buf.writeln('  ${e.key}: $p%');
    }

    buf.writeln('打分：${sc['score'] ?? 'N/A'}');
    return buf.toString();
  }

  Future<void> _runMain() async {
    FocusScope.of(context).requestFocus(FocusNode());

    if (_picked == null && _uploadedUrl == null) {
      _snack('请先选择并上传图片');
      return;
    }
    if (_uploadedUrl == null) {
      _snack('图片还未上传完成');
      return;
    }

    setState(() {
      _busy = true;
      _llmText = null;
      _responseText = null; // 清空旧结果
    });

    try {
      // 先做 ML
      await _predict();

      if (!_useLLM) {
        // 未勾选：直接展示 ML
        setState(() {
          _responseText = _mlResult;
        });
      } else {
        final cls = _mlClassify ?? {};
        final sc  = _mlScore ?? {};
        final predicted = cls['predicted_class']?.toString() ?? '未知';
        final confPct   = (((cls['confidence'] ?? 0) as num).toDouble() * 100).toStringAsFixed(2);
        final probsMap  = (cls['class_probabilities'] as Map? ?? {})
                            .map((k, v) => MapEntry(k.toString(), (v as num).toDouble()));
        final probsJson = jsonEncode(probsMap);
        final score     = sc['score']?.toString() ?? 'N/A';

        final finalPrompt = '''
  ${_promptCtrl.text}
  机器学习初步结果（供参考）
  - 分类：$predicted（置信度 $confPct%）
  - 各类别概率：$probsJson
  - 机器评分：$score
  请只输出中文整段文字，不要使用 Markdown。
  ''';

        final llmText = await _askPost(_uploadedUrl!, finalPrompt, streamUpdate: false);

        setState(() {
          _llmText = llmText;
          _responseText = '${_mlResult ?? ''}\n\n—— 大模型综合分析 ——\n${_llmText ?? ''}';
        });
      }

      _snack('分析完成');
    } catch (e) {
      setState(() {
        _responseText = '请求失败：$e';
      });
    } finally {
      setState(() {
        _busy = false;
      });
    }
  }

  void _snack(String msg) {
    // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
  }

  void dispose() {
    _promptCtrl.dispose();
    super.dispose();
  }

  Widget _applyLLMRow() {
    return InkWell(
      borderRadius: BorderRadius.circular(10),
      onTap: _openPromptSheet,
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 4),
        child: Row(
          children: [
            Checkbox(
              value: _useLLM,
              shape: const CircleBorder(),
              onChanged: (v) => setState(() => _useLLM = v ?? false),
            ),
            const SizedBox(width: 4),
            const Text('应用大模型',
                style: TextStyle(fontSize: 14, color: Colors.black54)),
            const Spacer(),
            const Icon(Icons.chevron_right, size: 20, color: Colors.black38),
          ],
        ),
      ),
    );
  }

  Widget build(BuildContext context) {
    if (!isLogined(context)) {
      return Scaffold(
        appBar: AppBar(
          toolbarHeight: 0,
          backgroundColor: os_white,
          surfaceTintColor: os_white,
        ),
        backgroundColor: os_white,
        body: ListView(children: [
          Container(
            padding: EdgeInsets.only(left: 20, right: 20),
            child: Column(
              children: [
                Container(height: 200),
                Icon(
                  Icons.person,
                  size: 50,
                  color: os_color,
                ),
                Container(height: 15),
                Text(
                  "请先登录",
                  style: TextStyle(
                    fontSize: 22,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                Container(height: 10),
                Text(
                  "登录后方可使用AI问问功能",
                  style: TextStyle(fontSize: 16),
                ),
                Container(height: 60),
                ElevatedButton(
                  style: ButtonStyle(
                    elevation: WidgetStatePropertyAll(0),
                    backgroundColor: WidgetStatePropertyAll(os_color_opa),
                    foregroundColor: WidgetStatePropertyAll(os_color),
                    padding: WidgetStatePropertyAll(
                      EdgeInsets.symmetric(vertical: 15, horizontal: 40),
                    ),
                  ),
                  onPressed: () {
                    Navigator.of(context).pushNamed("/login_with_pwd");
                  },
                  child: Text(
                    "前往登录",
                    style: XSTextStyle(
                      context: context,
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                )
              ],
            ),
          )
        ]),
      );
    }
    return _buildUploadMode();
  }

  Widget _buildUploadMode() {
    final Widget preview;
    if (_picked == null && !_uploadedOk) {
      preview = Container(
        height: 210,
        // width: double.infinity,
        decoration: BoxDecoration(
          color: Colors.grey.shade200,
          // border: Border.all(color: Colors.grey.shade300),
          borderRadius: BorderRadius.circular(20),
        ),
        child: const Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.image_outlined, size: 36, color: Colors.grey),
              SizedBox(height: 8),
              Text('点击左边按钮，选择图片',
                  style: TextStyle(color: Colors.grey, fontSize: 14)),
            ],
          ),
        ),
      );
    } else {
      Widget img;
      if (_picked != null) {
        img = ClipRRect(
          borderRadius: BorderRadius.circular(20),
          child: Image.file(
            File(_picked!.path),
            height: 210,
            width: double.infinity,
            fit: BoxFit.cover,
          ),
        );
      } else {
        img = ClipRRect(
          borderRadius: BorderRadius.circular(20),
          child: Image.network(
            _uploadedUrl!,
            height: 210,
            width: double.infinity,
            fit: BoxFit.cover,
            loadingBuilder: (context, child, loadingProgress) {
              if (loadingProgress == null) return child;
              return Center(
                child: CircularProgressIndicator(
                  value: loadingProgress.expectedTotalBytes != null
                      ? loadingProgress.cumulativeBytesLoaded /
                          loadingProgress.expectedTotalBytes!
                      : null,
                ),
              );
            },
            errorBuilder: (context, error, stackTrace) {
              return Container(
                height: 210,
                width: double.infinity,
                decoration: BoxDecoration(
                  color: Colors.grey.shade100,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: const Center(
                  child: Icon(Icons.error, color: Colors.red),
                ),
              );
            },
          ),
        );
      }

      preview = Stack(
        alignment: Alignment.center,
        children: [
          img,
          if (_uploadedOk)
            Container(
              height: 210,
              width: double.infinity,
              decoration: BoxDecoration(
                color: Colors.black.withOpacity(0.12),
                borderRadius: BorderRadius.circular(20),
              ),
              child: Center(
                child: CircleAvatar(
                  radius: 28,
                  backgroundColor: os_white,
                  child:
                      Icon(Icons.check_circle, color: Colors.green, size: 40),
                ),
              ),
            ),
        ],
      );
    }

    return Stack(
      children: [
        Scaffold(
          appBar: AppBar(
            toolbarHeight: 0,
            backgroundColor: os_white,
            surfaceTintColor: os_white,
          ),
          backgroundColor: os_white,
          body: SingleChildScrollView(
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                // 选图/拍照
                Row(
                  children: [
                    Column(
                      children: [
                        SizedBox(
                          height: 100,
                          width: 100,
                          child: myInkWell(
                            color: os_color,
                            radius: 20,
                            tap: () {
                              _pick(ImageSource.camera);
                            },
                            widget: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Icon(
                                  Icons.photo_camera,
                                  color: os_white,
                                ),
                                Container(height: 10),
                                Text(
                                  '拍照',
                                  style: TextStyle(
                                    fontSize: 14,
                                    fontWeight: FontWeight.bold,
                                    color: os_white,
                                  ),
                                )
                              ],
                            ),
                          ),
                        ),
                        const SizedBox(height: 10),
                        SizedBox(
                          height: 100,
                          width: 100,
                          child: myInkWell(
                            color: os_color_opa,
                            radius: 20,
                            tap: () {
                              _pick(ImageSource.gallery);
                            },
                            widget: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Icon(
                                  Icons.photo_library,
                                  color: os_color,
                                ),
                                Container(height: 10),
                                Text(
                                  '相册',
                                  style: TextStyle(
                                    fontSize: 14,
                                    fontWeight: FontWeight.bold,
                                    color: os_color,
                                  ),
                                )
                              ],
                            ),
                          ),
                        ),
                      ],
                    ),
                    Container(width: 10),
                    Expanded(child: preview),
                  ],
                ),
                if (_progress != null) ...[
                  const SizedBox(height: 8),
                  LinearProgressIndicator(
                    value: _progress,
                    color: os_color,
                  ),
                  const SizedBox(height: 4),
                  Text('${((_progress ?? 0) * 100).toStringAsFixed(0)}%'),
                ],
                const SizedBox(height: 10),
                SizedBox(
                  height: 63,
                  width: double.infinity,
                  child: FilledButton.icon(
                    onPressed: _runMain,
                    icon: const Icon(Icons.smart_toy),
                    label: const Text(
                      '模型预测',
                      style:
                          TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
                    ),
                    style: FilledButton.styleFrom(
                      backgroundColor: Colors.blueAccent,
                      foregroundColor: os_white,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20)),
                    ),
                  ),
                ),
                const SizedBox(height: 12),
                _applyLLMRow(),
                const SizedBox(height: 6),

                if (_busy)
                  Column(
                    children: [
                      Container(height: 15),
                      LinearProgressIndicator(
                        color: os_color,
                      ),
                    ],
                  ),

                // 显示模型响应内容
                if (_responseText != null &&
                    _responseText!.trim().isNotEmpty) ...[
                  const SizedBox(height: 10),
                  Container(
                    width: double.infinity,
                    padding: const EdgeInsets.all(18),
                    decoration: BoxDecoration(
                      color: Colors.grey.shade50,
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(color: Colors.grey.shade300),
                    ),
                    child: SelectableText(
                      _responseText!,
                      style: const TextStyle(fontSize: 15),
                    ),
                  ),
                ],
                const SizedBox(height: 32),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
